package com.resume.aipeople.service.ai;

import com.baidu.aip.speech.AipSpeech;
import com.resume.aipeople.controller.AudioController;
import com.resume.aipeople.entity.VoiceCache;
import com.resume.aipeople.repository.VoiceCacheRepository;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import reactor.core.publisher.Mono;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@Slf4j
public class VoiceService {
    
    private final AipSpeech aipSpeech;
    private final VoiceCacheRepository voiceCacheRepository;
    
    @Value("${baidu.voice.api.key:your-baidu-api-key}")
    private String baiduApiKey;
    
    @Value("${baidu.voice.secret.key:your-baidu-secret-key}")
    private String baiduSecretKey;
    
    @Value("${baidu.voice.app.id:your-app-id}")
    private String baiduAppId;
    
    private final WebClient webClient = WebClient.builder()
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .exchangeStrategies(
                ExchangeStrategies.builder()
                    .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024)) // 10MB
                    .build()
            )
            .build();
    
    public Mono<String> textToSpeech(String text, String characterName) {
        try {
            // 生成文本哈希值用于缓存查找
            String textHash = generateTextHash(text, characterName);
            
            // 首先检查缓存中是否已存在该语音
            Optional<VoiceCache> cachedVoice = voiceCacheRepository.findByTextHash(textHash);
            if (cachedVoice.isPresent()) {
                VoiceCache voiceCache = cachedVoice.get();
                voiceCache.incrementAccessCount();
                voiceCacheRepository.save(voiceCache);
                
                log.info("从缓存中获取语音: textHash={}, 访问次数={}", textHash, voiceCache.getAccessCount());
                
                // 从缓存中获取音频数据并保存到AudioController
                String audioUrl = saveCachedAudioData(voiceCache);
                return Mono.just(audioUrl);
            }
            
            log.info("缓存中未找到语音，开始TTS转换: textHash={}", textHash);
            
            // 如果百度API配置不完整，直接返回模拟URL
            if (baiduApiKey.equals("your-baidu-api-key") || baiduSecretKey.equals("your-baidu-secret-key")) {
                log.info("百度语音API未配置，使用模拟TTS");
                String mockUrl = generateMockAudioUrl(text, characterName);
                // 将模拟音频也保存到缓存中
                saveMockAudioToCache(text, characterName, textHash);
                return Mono.just(mockUrl);
            }
            
            // 获取百度Access Token并调用TTS
            return getBaiduAccessToken()
                    .flatMap(token -> {
                        String ttsUrl = "https://tsn.baidu.com/text2audio";
                        
                        // 百度TTS API参数
                        String encodedText = URLEncoder.encode(text, StandardCharsets.UTF_8);
                        String voicePer = selectVoiceForCharacter(characterName);
                        
                        // 验证参数
                        if (encodedText.isEmpty()) {
                            log.error("编码后的文本为空，原始文本: {}", text);
                            String mockUrl = generateMockAudioUrl(text, characterName);
                            saveMockAudioToCache(text, characterName, textHash);
                            return Mono.just(mockUrl);
                        }
                        
                        if (token == null || token.trim().isEmpty()) {
                            log.error("百度Access Token为空");
                            String mockUrl = generateMockAudioUrl(text, characterName);
                            saveMockAudioToCache(text, characterName, textHash);
                            return Mono.just(mockUrl);
                        }
                        
                        log.info("百度TTS参数: text长度={}, voice={}, token长度={}", 
                                encodedText.length(), voicePer, token.length());
                        
                        String params = "tex=" + encodedText 
                                + "&lan=zh"
                                + "&ctp=1"
                                + "&cuid=aipeople"
                                + "&tok=" + token
                                + "&per=" + voicePer
                                + "&spd=5&pit=5&vol=5&aue=3";
                        
                        return webClient.post()
                                .uri(ttsUrl)
                                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                                .bodyValue(params)
                                .retrieve()
                                .bodyToMono(byte[].class)
                                .map(audioData -> {
                                    if (audioData != null && audioData.length > 0) {
                                        // 检查是否是JSON错误响应
                                        String responseStr = new String(audioData);
                                        if (responseStr.startsWith("{") || responseStr.contains("error")) {
                                            log.error("百度TTS返回错误响应: {}", responseStr);
                                            
                                            // 检查具体错误类型并提供详细解决方案
                                            if (responseStr.contains("No permission") || responseStr.contains("err_no\":502")) {
                                                log.error("===============================================");
                                                log.error("百度TTS权限错误 - 解决方案：");
                                                log.error("1. 登录百度智能云控制台：https://console.bce.baidu.com/");
                                                log.error("2. 进入「语音技术」服务");
                                                log.error("3. 确保已开通「语音合成（TTS）」服务");
                                                log.error("4. 领取「语音合成-基础音库」免费额度");
                                                log.error("5. 检查API Key是否有TTS权限");
                                                log.error("当前使用API Key: {}...", baiduApiKey.substring(0, Math.min(8, baiduApiKey.length())));
                                                log.error("===============================================");
                                            } else if (responseStr.contains("quota")) {
                                                log.error("百度TTS配额不足：请检查控制台的免费额度或充值");
                                            } else if (responseStr.contains("frequency")) {
                                                log.error("百度TTS请求频率过高：请稍后重试");
                                            }
                                            String mockUrl = generateMockAudioUrl(text, characterName);
                                            saveMockAudioToCache(text, characterName, textHash);
                                            return mockUrl;
                                        }
                                        
                                        // 检查是否是有效的音频文件头
                                        if (audioData.length < 100) {
                                            log.warn("百度TTS返回的音频数据太小 ({} bytes)，可能是错误响应: {}", 
                                                    audioData.length, new String(audioData));
                                            String mockUrl = generateMockAudioUrl(text, characterName);
                                            saveMockAudioToCache(text, characterName, textHash);
                                            return mockUrl;
                                        }
                                        
                                        // 保存真实的音频数据到缓存和AudioController
                                        String audioUrl = saveAudioDataToCache(audioData, text, characterName, textHash);
                                        log.info("百度TTS成功，音频大小: {} bytes, URL: {}", audioData.length, audioUrl);
                                        return audioUrl;
                                    } else {
                                        log.warn("百度TTS返回空音频数据");
                                        String mockUrl = generateMockAudioUrl(text, characterName);
                                        saveMockAudioToCache(text, characterName, textHash);
                                        return mockUrl;
                                    }
                                });
                    })
                    .doOnError(error -> {
                        log.error("百度TTS服务调用失败", error);
                        // 错误时也保存模拟音频到缓存
                        saveMockAudioToCache(text, characterName, textHash);
                    })
                    .onErrorReturn(generateMockAudioUrl(text, characterName));
                    
        } catch (Exception e) {
            log.error("TTS转换异常", e);
            String mockUrl = generateMockAudioUrl(text, characterName);
            String textHash = generateTextHash(text, characterName);
            saveMockAudioToCache(text, characterName, textHash);
            return Mono.just(mockUrl);
        }
    }
    
    private Mono<String> getBaiduAccessToken() {
        String tokenUrl = "https://aip.baidubce.com/oauth/2.0/token";
        
        return webClient.post()
                .uri(tokenUrl + "?grant_type=client_credentials&client_id=" + baiduApiKey + "&client_secret=" + baiduSecretKey)
                .retrieve()
                .bodyToMono(Map.class)
                .map(response -> (String) response.get("access_token"))
                .doOnError(error -> log.error("获取百度Access Token失败", error));
    }
    
    public Mono<String> speechToText(MultipartFile audioFile) {
        return Mono.fromCallable(() -> {
            try {
                // 如果百度API配置不完整，直接返回模拟文本
                if (baiduApiKey.equals("your-baidu-api-key") || baiduSecretKey.equals("your-baidu-secret-key")) {
                    log.info("百度语音API未配置，使用模拟ASR");
                    return mockSpeechToText(audioFile);
                }
                
                // 获取音频文件数据
                byte[] audioData = audioFile.getBytes();
                String format = detectAudioFormat(audioFile);
                int sampleRate = detectSampleRate(audioData, format);
                
                log.info("音频文件信息: 格式={}, 大小={}KB, 采样率={}", format, audioData.length/1024, sampleRate);
                
                // 设置识别参数 - 根据百度SDK文档优化
                HashMap<String, Object> options = new HashMap<>();
                options.put("cuid", "aipeople_" + System.currentTimeMillis()); // 用户唯一标识，加时间戳确保唯一
                options.put("dev_pid", 1537); // 普通话(纯中文识别) 语音近场识别模型，有标点，支持自定义词库
                
                log.debug("ASR参数: format={}, rate={}, cuid={}, dev_pid={}", 
                         format, sampleRate, options.get("cuid"), options.get("dev_pid"));
                
                // 多模型尝试：提升数字与短语音识别稳定性
                int[] devPidCandidates = new int[]{1537, 1536, 1936}; // 普通话近场(有标点)、普通话输入法、远场
                List<String> candidateResults = new ArrayList<>();
                
                for (int devPid : devPidCandidates) {
                    options.put("dev_pid", devPid);
                    String r = recognizeOnce(audioData, format, sampleRate, options);
                    if (r != null && !r.isBlank()) {
                        candidateResults.add(r);
                        log.info("ASR候选(dev_pid={}): {}", devPid, r);
                    }
                }
                
                String best = pickBestRecognition(candidateResults);
                if (best != null && !best.trim().isEmpty()) {
                    String normalized = normalizeDigits(best);
                    log.info("ASR最终结果: {} -> 规范化: {}", best, normalized);
                    return normalized;
                }
                
                // 如果所有模型都失败，尝试不同的音频格式
                log.warn("所有ASR模型都失败，尝试格式转换");
                String convertedFormat = tryFormatConversion(audioData, format);
                if (!convertedFormat.equals(format)) {
                    log.info("尝试转换格式: {} -> {}", format, convertedFormat);
                    String convertedResult = recognizeOnce(audioData, convertedFormat, sampleRate, options);
                    if (convertedResult != null && !convertedResult.trim().isEmpty()) {
                        log.info("格式转换后识别成功: {}", convertedResult);
                        return normalizeDigits(convertedResult);
                    }
                }
                
                // 最后尝试：返回更友好的错误信息而不是模拟结果
                log.error("语音识别完全失败，返回空结果");
                return "";
                
            } catch (Exception e) {
                log.error("语音识别异常", e);
                return mockSpeechToText(audioFile);
            }
        })
        .doOnError(error -> log.error("语音识别调用失败", error))
        .onErrorReturn(mockSpeechToText(audioFile));
    }
    
    /**
     * 单次识别调用并解析
     */
    private String recognizeOnce(byte[] audioData, String format, int sampleRate, HashMap<String, Object> options) {
        try {
            JSONObject result = aipSpeech.asr(audioData, format, sampleRate, options);
            log.info("百度ASR响应: {}", result.toString());
            if (result.has("err_no") && result.getInt("err_no") == 0) {
                if (result.has("result") && result.getJSONArray("result").length() > 0) {
                    return result.getJSONArray("result").getString(0);
                }
                return null;
            } else {
                int errorCode = result.optInt("err_no");
                String errorMsg = result.optString("err_msg", "未知错误");
                log.warn("百度ASR识别失败: {} (错误码: {})", errorMsg, errorCode);
                return null;
            }
        } catch (Exception e) {
            log.warn("ASR识别异常: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 选择最优识别结果：
     * - 优先包含数字/中文数字占比较高的结果
     * - 其次选择最短且无明显脏词的结果
     */
    private String pickBestRecognition(List<String> candidates) {
        if (candidates == null || candidates.isEmpty()) return null;
        String best = null;
        int bestScore = Integer.MIN_VALUE;
        for (String s : candidates) {
            int score = scoreForDigits(s) - profanityPenalty(s);
            if (score > bestScore) { bestScore = score; best = s; }
        }
        return best != null ? best.trim() : candidates.get(0).trim();
    }
    
    private int scoreForDigits(String s) {
        if (s == null) return 0;
        int digits = (int) s.chars().filter(ch -> Character.isDigit(ch)).count();
        int cnDigits = (int) s.chars().filter(ch -> "〇零一二三四五六七八九十百千两幺壹贰叁肆伍陆柒捌玖拾".indexOf(ch) >= 0).count();
        int len = Math.max(1, s.length());
        return (digits + cnDigits) * 4 - (len - (digits + cnDigits));
    }
    
    private int profanityPenalty(String s) {
        if (s == null) return 0;
        String[] bad = new String[]{"操你", "傻逼", "妈的"};
        for (String b : bad) if (s.contains(b)) return 8;
        return 0;
    }
    
    /**
     * 将常见口语数字规范化，便于后续使用
     */
    private String normalizeDigits(String s) {
        if (s == null) return null;
        String t = s;
        t = t.replace("幺", "一");
        t = t.replace("两", "二");
        t = t.replace("壹", "一").replace("贰", "二").replace("叁", "三").replace("肆", "四")
             .replace("伍", "五").replace("陆", "六").replace("柒", "七").replace("捌", "八")
             .replace("玖", "九").replace("拾", "十");
        return t;
    }
    
    private String selectVoiceForCharacter(String characterName) {
        switch (characterName) {
            case "哈利波特":
                return "106"; // 男声
            case "苏格拉底":
                return "103"; // 磁性男声
            case "艾丽莎博士":
                return "110"; // 女声
            default:
                return "1"; // 普通女声
        }
    }
    
    public String generateMockAudioUrl(String text, String characterName) {
        // 生成基于文本内容和角色的唯一ID
        String combined = text + "_" + characterName;
        String audioId = String.valueOf(Math.abs(combined.hashCode()));
        return "/api/audio/tts/" + audioId + ".wav"; // 使用WAV格式，兼容性更好
    }
    
    public String mockSpeechToText(MultipartFile audioFile) {
        String filename = audioFile.getOriginalFilename();
        return "这是模拟的语音识别结果，文件名: " + filename;
    }
    
    /**
     * 尝试格式转换，用于ASR识别失败时的备用方案
     */
    private String tryFormatConversion(byte[] audioData, String currentFormat) {
        // 如果当前是PCM但识别失败，尝试WAV格式
        if ("pcm".equals(currentFormat)) {
            log.info("PCM格式识别失败，尝试WAV格式");
            return "wav";
        }
        
        // 如果当前是WAV但识别失败，尝试PCM格式
        if ("wav".equals(currentFormat)) {
            log.info("WAV格式识别失败，尝试PCM格式");
            return "pcm";
        }
        
        // 对于其他格式，尝试PCM
        log.info("{}格式识别失败，尝试PCM格式", currentFormat);
        return "pcm";
    }
    
    private String getFileExtension(String filename) {
        if (filename == null || !filename.contains(".")) {
            return "wav";
        }
        return filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
    }
    
    private String detectAudioFormat(MultipartFile audioFile) {
        try {
            byte[] audioData = audioFile.getBytes();
            String filename = audioFile.getOriginalFilename();
            String contentType = audioFile.getContentType();
            
            log.debug("音频文件检测: filename={}, contentType={}, size={}bytes", 
                     filename, contentType, audioData.length);
            
            // 优先根据Content-Type判断（更准确）
            if (contentType != null) {
                if (contentType.contains("webm")) {
                    log.warn("检测到WebM格式（{}），转换为PCM处理（百度SDK推荐）", contentType);
                    return "pcm";
                }
                if (contentType.contains("wav")) {
                    log.info("根据ContentType检测为WAV格式");
                    return "wav";
                }
                if (contentType.contains("amr")) {
                    log.info("根据ContentType检测为AMR格式");
                    return "amr";
                }
                // 对于其他压缩格式，转换为PCM
                if (contentType.contains("ogg") || contentType.contains("mp4") || 
                    contentType.contains("m4a") || contentType.contains("opus")) {
                    log.warn("检测到{}格式，转换为PCM处理（百度SDK推荐）", contentType);
                    return "pcm";
                }
            }
            
            // 检查文件头来确定实际格式（只有在Content-Type不明确时才使用）
            if (audioData.length >= 12) {
                // 检查WAV格式 (RIFF...WAVE)
                if (audioData[0] == 'R' && audioData[1] == 'I' && audioData[2] == 'F' && audioData[3] == 'F' &&
                    audioData[8] == 'W' && audioData[9] == 'A' && audioData[10] == 'V' && audioData[11] == 'E') {
                    log.info("通过文件头检测到WAV格式音频");
                    return "wav";
                }
                
                // 检查AMR格式
                if (audioData[0] == '#' && audioData[1] == '!' && audioData[2] == 'A' && 
                    audioData[3] == 'M' && audioData[4] == 'R') {
                    log.info("通过文件头检测到AMR格式音频");
                    return "amr";
                }
                
                // 检查WebM格式 (EBML header)
                if (audioData[0] == 0x1A && audioData[1] == 0x45 && audioData[2] == (byte)0xDF && audioData[3] == (byte)0xA3) {
                    log.warn("通过文件头检测到WebM格式，转换为PCM处理");
                    return "pcm";
                }
            }
            
            // 最后才根据文件扩展名判断（最不可靠）
            if (filename != null) {
                String ext = filename.toLowerCase();
                if (ext.endsWith(".wav") && (contentType == null || !contentType.contains("webm"))) {
                    log.info("根据文件名检测为WAV格式");
                    return "wav";
                } else if (ext.endsWith(".amr")) {
                    log.info("根据文件名检测为AMR格式");
                    return "amr";
                } else if (ext.endsWith(".pcm")) {
                    log.info("根据文件名检测为PCM格式");
                    return "pcm";
                }
            }
            
            // 默认使用PCM格式（百度文档推荐）
            log.warn("无法确定音频格式，使用PCM格式（推荐格式），ContentType: {}", contentType);
            return "pcm";
            
        } catch (Exception e) {
            log.error("检测音频格式失败", e);
            return "pcm";
        }
    }
    
    private int detectSampleRate(byte[] audioData, String format) {
        // 只对真正的WAV格式文件尝试读取采样率
        if ("wav".equals(format) && audioData.length >= 28) {
            try {
                // 先验证这确实是WAV文件头
                if (audioData[0] == 'R' && audioData[1] == 'I' && audioData[2] == 'F' && audioData[3] == 'F' &&
                    audioData[8] == 'W' && audioData[9] == 'A' && audioData[10] == 'V' && audioData[11] == 'E') {
                    
                    // WAV文件的采样率在第24-27字节（小端序）
                    int sampleRate = (audioData[24] & 0xFF) | 
                                   ((audioData[25] & 0xFF) << 8) | 
                                   ((audioData[26] & 0xFF) << 16) | 
                                   ((audioData[27] & 0xFF) << 24);
                    
                    // 验证采样率是否为百度SDK支持的固定值：16000、8000
                    if (sampleRate == 16000) {
                        log.info("从WAV头部检测到采样率: {}Hz（百度推荐）", sampleRate);
                        return sampleRate;
                    } else if (sampleRate == 8000) {
                        log.info("从WAV头部检测到采样率: {}Hz", sampleRate);
                        return sampleRate;
                    } else if (sampleRate > 0 && sampleRate < 100000) {
                        log.warn("检测到采样率{}Hz，百度SDK只支持16000/8000Hz，使用16000Hz", sampleRate);
                    } else {
                        log.warn("检测到无效采样率{}Hz，可能不是标准WAV文件，使用16000Hz", sampleRate);
                    }
                } else {
                    log.warn("格式标记为WAV但文件头不匹配，可能是转换格式，使用16000Hz");
                }
            } catch (Exception e) {
                log.warn("从WAV头部读取采样率失败: {}", e.getMessage());
            }
        }
        
        // 对于PCM格式或无法检测的情况，使用默认采样率
        if ("pcm".equals(format)) {
            log.info("PCM格式使用默认采样率: 16000Hz（百度SDK推荐）");
        } else {
            log.info("使用默认采样率: 16000Hz（百度SDK推荐）");
        }
        return 16000;
    }
    
    private String saveAudioData(byte[] audioData, String text, String characterName) {
        // 生成唯一的音频ID - 百度TTS返回的应该是MP3格式
        String combined = text + "_" + characterName;
        String audioId = String.valueOf(Math.abs(combined.hashCode())) + ".mp3";
        
        // 将音频数据保存到AudioController的存储中
        AudioController.saveAudioData(audioId, audioData);
        
        return "/api/audio/tts/" + audioId;
    }
    
    /**
     * 生成文本哈希值用于缓存查找
     */
    private String generateTextHash(String text, String characterName) {
        try {
            String combined = text + "_" + characterName;
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashBytes = md.digest(combined.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("生成文本哈希失败", e);
            return String.valueOf(Math.abs((text + "_" + characterName).hashCode()));
        }
    }
    
    /**
     * 保存音频数据到缓存
     */
    private String saveAudioDataToCache(byte[] audioData, String text, String characterName, String textHash) {
        try {
            // 保存到AudioController
            String audioId = textHash + ".mp3";
            AudioController.saveAudioData(audioId, audioData);
            
            // 保存到数据库缓存
            VoiceCache voiceCache = new VoiceCache();
            voiceCache.setTextHash(textHash);
            voiceCache.setOriginalText(text);
            voiceCache.setCharacterName(characterName);
            voiceCache.setAudioData(audioData);
            voiceCache.setAudioFormat("mp3");
            voiceCache.setAudioSize((long) audioData.length);
            voiceCache.setTtsProvider("baidu");
            voiceCache.setAccessCount(1L);
            
            voiceCacheRepository.save(voiceCache);
            
            log.info("音频数据已保存到缓存: textHash={}, size={}bytes", textHash, audioData.length);
            
            return "/api/audio/tts/" + audioId;
        } catch (Exception e) {
            log.error("保存音频数据到缓存失败", e);
            // 如果缓存保存失败，仍然返回音频URL
            return saveAudioData(audioData, text, characterName);
        }
    }
    
    /**
     * 从缓存中获取音频数据并保存到AudioController
     */
    private String saveCachedAudioData(VoiceCache voiceCache) {
        try {
            String audioId = voiceCache.getTextHash() + "." + voiceCache.getAudioFormat();
            AudioController.saveAudioData(audioId, voiceCache.getAudioData());
            return "/api/audio/tts/" + audioId;
        } catch (Exception e) {
            log.error("从缓存获取音频数据失败", e);
            // 如果失败，重新生成模拟URL
            return generateMockAudioUrl(voiceCache.getOriginalText(), voiceCache.getCharacterName());
        }
    }
    
    /**
     * 保存模拟音频到缓存
     */
    private void saveMockAudioToCache(String text, String characterName, String textHash) {
        try {
            // 检查是否已经存在
            if (voiceCacheRepository.findByTextHash(textHash).isPresent()) {
                return;
            }
            
            // 创建模拟音频数据（简单的静音音频）
            byte[] mockAudioData = generateMockAudioData();
            
            VoiceCache voiceCache = new VoiceCache();
            voiceCache.setTextHash(textHash);
            voiceCache.setOriginalText(text);
            voiceCache.setCharacterName(characterName);
            voiceCache.setAudioData(mockAudioData);
            voiceCache.setAudioFormat("wav");
            voiceCache.setAudioSize((long) mockAudioData.length);
            voiceCache.setTtsProvider("mock");
            voiceCache.setAccessCount(1L);
            
            voiceCacheRepository.save(voiceCache);
            
            log.info("模拟音频已保存到缓存: textHash={}", textHash);
        } catch (Exception e) {
            log.error("保存模拟音频到缓存失败", e);
        }
    }
    
    /**
     * 生成模拟音频数据（简单的WAV格式静音）
     */
    private byte[] generateMockAudioData() {
        // 生成一个简单的WAV格式静音音频（1秒，16kHz，16bit）
        int sampleRate = 16000;
        int duration = 1; // 1秒
        int numSamples = sampleRate * duration;
        int numChannels = 1;
        int bitsPerSample = 16;
        
        // WAV文件头
        byte[] header = new byte[44];
        header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F';
        // 文件大小
        int fileSize = 36 + numSamples * numChannels * (bitsPerSample / 8);
        header[4] = (byte) (fileSize & 0xff);
        header[5] = (byte) ((fileSize >> 8) & 0xff);
        header[6] = (byte) ((fileSize >> 16) & 0xff);
        header[7] = (byte) ((fileSize >> 24) & 0xff);
        
        header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E';
        header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' ';
        
        // fmt chunk size
        header[16] = 16; header[17] = 0; header[18] = 0; header[19] = 0;
        // audio format (PCM)
        header[20] = 1; header[21] = 0;
        // number of channels
        header[22] = (byte) numChannels; header[23] = 0;
        // sample rate
        header[24] = (byte) (sampleRate & 0xff);
        header[25] = (byte) ((sampleRate >> 8) & 0xff);
        header[26] = (byte) ((sampleRate >> 16) & 0xff);
        header[27] = (byte) ((sampleRate >> 24) & 0xff);
        
        // byte rate
        int byteRate = sampleRate * numChannels * (bitsPerSample / 8);
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        
        // block align
        header[32] = (byte) (numChannels * (bitsPerSample / 8)); header[33] = 0;
        // bits per sample
        header[34] = (byte) bitsPerSample; header[35] = 0;
        
        header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a';
        
        // data size
        int dataSize = numSamples * numChannels * (bitsPerSample / 8);
        header[40] = (byte) (dataSize & 0xff);
        header[41] = (byte) ((dataSize >> 8) & 0xff);
        header[42] = (byte) ((dataSize >> 16) & 0xff);
        header[43] = (byte) ((dataSize >> 24) & 0xff);
        
        // 创建静音数据
        byte[] audioData = new byte[header.length + dataSize];
        System.arraycopy(header, 0, audioData, 0, header.length);
        // 静音数据部分已经是0，不需要额外设置
        
        return audioData;
    }
    
    @Data
    public static class TTSRequest {
        private String text;
        private String voice;
        private Double speed;
        private Double pitch;
        private String format;
    }
    
    @Data
    public static class TTSResponse {
        private Boolean success;
        private String audioUrl;
        private String error;
    }
    
    @Data
    public static class ASRRequest {
        private String audio;
        private String format;
        private String language;
    }
    
    @Data
    public static class ASRResponse {
        private Boolean success;
        private String text;
        private Double confidence;
        private String error;
    }
}
